/**
 * File: MaqContigProcessor.java
 * Created by: mhaimel
 * Created on: 6 Jul 2009
 * CVS:  $Id: MaqContigProcessor.java,v 1.2 2009/10/09 15:12:39 mhaimel Exp $
 */
package uk.ac.ebi.curtain.processor.maq.impl;


import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.CRC32;

import org.apache.commons.lang.StringUtils;

import uk.ac.ebi.curtain.controller.maq.MaqBean;
import uk.ac.ebi.curtain.controller.maq.MaqContigOutputBean;
import uk.ac.ebi.curtain.processor.AbstractProcessor;
import uk.ac.ebi.curtain.util.ExecutionService;
import uk.ac.ebi.curtain.utils.CurtainUncheckedException;
import uk.ac.ebi.curtain.utils.data.FileType;
import uk.ac.ebi.curtain.utils.file.FileInfo;

import com.google.inject.Inject;

/**
 * Statefull object
 * 
 * @author mhaimel
 *
 */
public class MaqContigProcessor extends AbstractProcessor<MaqBean, MaqContigOutputBean> {

	private static final String FASTA2BFA_OPT = "fasta2bfa";
	private ExecutionService executionService;
	private MaqContigOutputBean outBean;
	
	
	public MaqContigProcessor() {
		// do nothing
	}

	@Override
	protected MaqContigOutputBean buildReturnObject() {
		return getOutBean();
	}

	@Override
	public void process() {
		setOutBean(new MaqContigOutputBean());
		for(FileInfo contig : getInput().getContigFiles()){
			File bfaFile = buildContigBfaFile(contig);
			if(isForceShutdown()){
				getLog().warn("FORCE shutdown!");
				break;
			}
			runMaqFasta2Bfa(contig, bfaFile);
			getOutBean().addContigFile(bfaFile);
		}
	}
	
	public void runMaqFasta2Bfa(FileInfo contig, File fasta2bfa){
		getLog().info("Transform Contig 2 maq bfa file ...");
		File fa = getFastaFile(contig);
		List<String> cmds = new ArrayList<String>();
		cmds.add(getMaqExecCmd());
		cmds.add(FASTA2BFA_OPT);
		cmds.add(fa.getAbsolutePath());
		cmds.add(fasta2bfa.getAbsolutePath());
		File logFile = getNextFile(getBaseDir(), fasta2bfa.getName()+"_", ".log");
		File errFile = getNextFile(getBaseDir(), fasta2bfa.getName()+"_", ".err");
		if(isForceShutdown()){
			getLog().warn("FORCE shutdown!");
			return;
		}
		getExecutionService().exec(getBaseDir(), cmds.toArray(new String[0]), logFile, errFile,false,true);
		getLog().info("Finished transforming Contig 2 maq file!");
	}
	
	private File buildContigBfaFile(FileInfo fileInfo) {
		getLog().info("Transform contig to bfa ...");		
		CRC32 crc = new CRC32();
		crc.update(fileInfo.getFile().getAbsolutePath().getBytes());
		String hex = Long.toHexString(crc.getValue());
		File bfaFile = new File(getInput().getContigDir(),fileInfo.getFile().getName()+"_"+hex+".bfa");
		if(bfaFile.exists() && !bfaFile.delete()){
			throw new CurtainUncheckedException("Not able to delete file: " + bfaFile);
		}
		return bfaFile;
	}	
	

	protected File getNextFile(File dir, String prefix,String postfix){
		return getExecutionService().getNextFile(dir, prefix, postfix);
	}
	
	private File getBaseDir() {
		return getInput().getContigDir();
	}

	private File getFastaFile(FileInfo contig) {
		if(contig.getFileType().equals(FileType.fasta)){
			return contig.getFile();
		} else {
			throw new IllegalArgumentException(
					"Only Contig files in fasta supported for now!");
		}
	}
	
	private String getMaqExecCmd() {
		String cmd = getConfig().getMaqExec();
		if(StringUtils.isEmpty(cmd)){
			throw new IllegalArgumentException(
					"No Maq executeable command provided!!");
		}
		return cmd;
	}

	@Inject
	public void setExecutionService(ExecutionService executionService) {
		this.executionService = executionService;
	}

	protected ExecutionService getExecutionService() {
		return executionService;
	}

	private void setOutBean(MaqContigOutputBean outBean) {
		this.outBean = outBean;
	}

	private MaqContigOutputBean getOutBean() {
		return outBean;
	}	

}
